/*=============================================================================
  D3DRenderThrread.cpp : D3D specific thread functions.
  Copyright 2001 Crytek Studios. All Rights Reserved.

  Revision history:
    * Created by Honich Andrey

=============================================================================*/

#include "StdAfx.h"
#include "DriverD3D.h"

#include "D3DStereo.h"

#include <IFlashPlayer.h>

//=======================================================================


bool CD3D9Renderer::RT_CreateDevice()
{
	MEMSTAT_CONTEXT(EMemStatContextTypes::MSC_D3D, 0, "Renderer CreateDevice");

#ifdef WIN32
  if (!m_bShaderCacheGen && !SetWindow(m_width, m_height, m_bFullScreen, m_hWnd))
    return false;
#endif

  return SetRes();
}

HRESULT CD3D9Renderer::RT_CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, UINT Pool, void** ppVertexBuffer, HANDLE* pSharedHandle)
{
#if defined (DIRECT3D9)
  return m_pd3dDevice->CreateVertexBuffer(Length, Usage, FVF, (D3DPOOL)Pool, (D3DVertexBuffer**)ppVertexBuffer, pSharedHandle);
#elif defined (DIRECT3D10)
  assert(0);
#endif
  return S_OK;
}
HRESULT CD3D9Renderer::RT_CreateIndexBuffer(UINT Length, DWORD Usage, DWORD Format, UINT Pool, void** ppIndexBuffer, HANDLE* pSharedHandle)
{
#if defined (DIRECT3D9)
  return m_pd3dDevice->CreateIndexBuffer(Length, Usage, (D3DFORMAT)Format, (D3DPOOL)Pool, (D3DIndexBuffer**)ppIndexBuffer, pSharedHandle);
#elif defined (DIRECT3D10)
  assert(0);
#endif
  return S_OK;
}

void CD3D9Renderer::RT_ReleaseVBStream(void *pVB, int nStream)
{
  D3DVertexBuffer *pBuf = (D3DVertexBuffer *)pVB;
#if defined (DIRECT3D9)
  if (pBuf == m_RP.m_VertexStreams[nStream].pStream)
  {
    m_RP.m_VertexStreams[nStream].pStream = NULL;
    m_pd3dDevice->SetStreamSource(nStream, NULL, 0, 0);
  }
#endif
  SAFE_RELEASE(pBuf);
}
void CD3D9Renderer::RT_ReleaseCB(void *pVCB)
{
#if defined (DIRECT3D10)
  ID3D11Buffer* pCB = (ID3D11Buffer *)pVCB;
  CHWShader_D3D::mfUnbindCB(pCB);
  SAFE_RELEASE(pCB);
#endif
}

void CD3D9Renderer::RT_TextureFill(CTexture* pTex, DWORD color)
{
#if defined (DIRECT3D9)
	D3DSurface *pSurf = pTex->GetSurface(0, 0);
	if (!pSurf)
		return;
	HRESULT hr = m_pd3dDevice->ColorFill(pSurf, 
		NULL, (D3DCOLOR)color);
	SAFE_RELEASE(pSurf);
#elif defined (DIRECT3D10)
	assert(0);
#endif
}

HRESULT CD3D9Renderer::RT_CreateVertexShader(DWORD *pBuf, void **pShader, void *pI)
{
#if defined (DIRECT3D9)
  HRESULT hr = S_OK;
  hr = m_pd3dDevice->CreateVertexShader(pBuf, (D3DVertexShader **)pShader);
  if (FAILED(hr))
    return hr;















































#elif defined (DIRECT3D10)
  assert(0);
#endif
  return S_OK;
}
HRESULT CD3D9Renderer::RT_CreatePixelShader(DWORD *pBuf, void **pShader)
{
#if defined (DIRECT3D9)
  return m_pd3dDevice->CreatePixelShader(pBuf, (D3DPixelShader **)pShader);
#elif defined (DIRECT3D10)
  assert(0);
#endif
  return S_OK;
}

void CD3D9Renderer::RT_DrawDynVB(int Pool, uint32 nVerts)
{
}


void CD3D9Renderer::RT_DrawDynVB(SVF_P3F_C4B_T2F *pBuf, uint16 *pInds, uint32 nVerts, uint32 nInds, const PublicRenderPrimitiveType nPrimType)
{
#if defined (DIRECT3D9)
  if (FAILED(m_pd3dDevice->TestCooperativeLevel()))
    return;
#endif

  HRESULT h;




  DynamicVB<byte>& VB = m_DynVB[POOL_P3F_COL4UB_TEX2F];

  uint32 nOffs, nIOffs;
  SVF_P3F_C4B_T2F *pDst = (SVF_P3F_C4B_T2F *)VB.LockVB(nVerts, nOffs);
  assert(pDst);
  if (!pDst)
    return;


//#ifdef CAFE
  bool bTempInds = false;
  /*if (!pInds)
  {
    bTempInds = true;
    pInds = new uint16[nVerts];
    for (int i=0; i<nVerts; i++)
    {
      pInds[i] = i;
    }
    nInds = nVerts;
    //nOffs = 0;
  }*/
//#endif

  uint16 *pDstInds = NULL;
  if (pInds)
    pDstInds = m_DynIB.LockIB(nInds, nIOffs);

  cryMemcpy(pDst, pBuf, nVerts*sizeof(SVF_P3F_C4B_T2F),MC_CPU_TO_GPU);
  if (pDstInds)
  {
    cryMemcpy(pDstInds, pInds, nInds*sizeof(short),MC_CPU_TO_GPU);
  }

  VB.UnlockVB();
  if (pDstInds)
    m_DynIB.UnlockIB();
  FX_SetFPMode();

  // Bind our vertex as the first data stream of our device
	// Render triangles from the data stream

  if (!FAILED(FX_SetVertexDeclaration(0, eVF_P3F_C4B_T2F)))
  {
    h = VB.Bind();
    assert(SUCCEEDED(h));

    if (pDstInds)
    {
      h = m_DynIB.Bind();
			assert(SUCCEEDED(h));
			FX_DrawIndexedPrimitive(GetInternalPrimitiveType(nPrimType), nOffs, 0, nVerts, nIOffs, nInds);
    }
    else
    {
      FX_DrawPrimitive(GetInternalPrimitiveType(nPrimType), nOffs, nVerts);
    }
  }
//#ifdef CAFE
  if (bTempInds)
    delete [] pInds;
//#endif
}

void CD3D9Renderer::RT_Draw2dImageInternal(C2dImage *images, uint32 numImages, bool stereoLeftEye)
{
	bool bSaveZTest = ((m_RP.m_CurState & GS_NODEPTHTEST) == 0);
	SetCullMode(R_CULL_DISABLE);

	float maxParallax = 0;
	float screenDist = 0;

	if (GetS3DRend().IsStereoEnabled())
	{
		maxParallax = GetS3DRend().GetMaxSeparationScene();
		screenDist = GetS3DRend().GetZeroParallaxPlaneDist();
	}

	// Set orthographic projection
	m_RP.m_TI[m_RP.m_nProcessThreadID].m_matProj->Push();
	Matrix44A *m = m_RP.m_TI[m_RP.m_nProcessThreadID].m_matProj->GetTop();
	mathMatrixOrthoOffCenterLH(m, 0.0f, (float)m_width, (float)m_height, 0.0f, 0.0f, 1.0f);
	m_RP.m_TI[m_RP.m_nProcessThreadID].m_matView->Push();
	m = m_RP.m_TI[m_RP.m_nProcessThreadID].m_matView->GetTop();
	m_RP.m_TI[m_RP.m_nProcessThreadID].m_matView->LoadIdentity();
	
	// Create dynamic geometry
	uint32 nOffs;
	SVF_P3F_C4B_T2F *vQuad = (SVF_P3F_C4B_T2F *)m_DynVB[POOL_P3F_COL4UB_TEX2F].LockVB(numImages * 4, nOffs);
	if (!vQuad)
	{
		m_RP.m_TI[m_RP.m_nProcessThreadID].m_matProj->Pop();
		m_RP.m_TI[m_RP.m_nProcessThreadID].m_matView->Pop();
		return;
	}
	for (uint32 i = 0; i < numImages; ++i)
	{
		C2dImage &img = images[i];
		uint32 baseIdx = i * 4;
		
		float parallax = 0;
		if (img.stereoDepth > 0)
			parallax = 800 * maxParallax * (1 - screenDist / img.stereoDepth);
		
		float xpos = (float)ScaleCoordX(img.xpos + parallax * (stereoLeftEye ? -1 : 1));
		float w = (float)ScaleCoordX(img.w);
		float ypos = (float)ScaleCoordY(img.ypos);
		float h = (float)ScaleCoordY(img.h);
		
	#if HALF_PIXEL_SHIFT_NEEDED
		float fx = xpos-0.5f;
		float fy = ypos-0.5f;
	#else
		float fx = xpos;
		float fy = ypos;
	#endif
		
		if (img.angle != 0)
		{
			float xsub=(float)(xpos+w/2.0f);
			float ysub=(float)(ypos+h/2.0f);

			float x ,y, x1, y1;
			float mcos=cry_cosf(DEG2RAD(img.angle));
			float msin=cry_sinf(DEG2RAD(img.angle));

			x=xpos-xsub;
			y=ypos-ysub;
			x1=x*mcos-y*msin;
			y1=x*msin+y*mcos;
			x1+=xsub;y1+=ysub;
			vQuad[baseIdx].xyz.x = x1;
			vQuad[baseIdx].xyz.y = y1;

			x=xpos+w-xsub;
			y=ypos-ysub;
			x1=x*mcos-y*msin;
			y1=x*msin+y*mcos;
			x1+=xsub;y1+=ysub;
			vQuad[baseIdx+1].xyz.x = x1;//fx + fw;
			vQuad[baseIdx+1].xyz.y = y1;// fy;

			x=xpos+w-xsub;
			y=ypos+h-ysub;
			x1=x*mcos-y*msin;
			y1=x*msin+y*mcos;
			x1+=xsub;y1+=ysub;
			vQuad[baseIdx+3].xyz.x = x1;//fx + fw;
			vQuad[baseIdx+3].xyz.y = y1;//fy + fh;

			x=xpos-xsub;
			y=ypos+h-ysub;
			x1=x*mcos-y*msin;
			y1=x*msin+y*mcos;
			x1+=xsub;y1+=ysub;
			vQuad[baseIdx+2].xyz.x = x1;//fx;
			vQuad[baseIdx+2].xyz.y = y1;//fy + fh;
		}
		else
		{
			vQuad[baseIdx].xyz.x = fx;
			vQuad[baseIdx].xyz.y = fy;

			vQuad[baseIdx+1].xyz.x = fx + w;
			vQuad[baseIdx+1].xyz.y = fy;

			vQuad[baseIdx+2].xyz.x = fx;
			vQuad[baseIdx+2].xyz.y = fy + h;

			vQuad[baseIdx+3].xyz.x = fx + w;
			vQuad[baseIdx+3].xyz.y = fy + h;
		}

		vQuad[baseIdx+0].st = Vec2(img.s0, 1.0f-img.t0);
		vQuad[baseIdx+1].st = Vec2(img.s1, 1.0f-img.t0);
		vQuad[baseIdx+2].st = Vec2(img.s0, 1.0f-img.t1);
		vQuad[baseIdx+3].st = Vec2(img.s1, 1.0f-img.t1);

		for(int j = 0; j < 4; ++j)
		{
			vQuad[baseIdx+j].color.dcolor = img.col;
			vQuad[baseIdx+j].xyz.z = img.z;
		}
	}
	m_DynVB[POOL_P3F_COL4UB_TEX2F].UnlockVB();
	
	CTexture *prevTex = NULL;
	EF_SetColorOp(eCO_REPLACE, eCO_REPLACE, (eCA_Diffuse|(eCA_Diffuse<<3)), (eCA_Diffuse|(eCA_Diffuse<<3)));
	FX_SetFPMode();
	
	// Bind vertex buffer as first data stream of device
	m_DynVB[POOL_P3F_COL4UB_TEX2F].Bind();
	if (FAILED(FX_SetVertexDeclaration(0, eVF_P3F_C4B_T2F)))
	{
		m_RP.m_TI[m_RP.m_nProcessThreadID].m_matView->Pop();
		m_RP.m_TI[m_RP.m_nProcessThreadID].m_matProj->Pop();
		return;
	}

	// Draw quads
	for (uint32 i = 0; i < numImages; ++i)
	{
		C2dImage &img = images[i];
		
		if (img.pTex != prevTex)
		{
			prevTex = img.pTex;
			if (img.pTex)
			{
				img.pTex->Apply(0);
				EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, DEF_TEXARG0, DEF_TEXARG0);
			}
			else
				EF_SetColorOp(eCO_REPLACE, eCO_REPLACE, (eCA_Diffuse|(eCA_Diffuse<<3)), (eCA_Diffuse|(eCA_Diffuse<<3)));

			FX_SetFPMode();
      if (FAILED(FX_SetVertexDeclaration(0, eVF_P3F_C4B_T2F)))
      {
        m_RP.m_TI[m_RP.m_nProcessThreadID].m_matView->Pop();
        m_RP.m_TI[m_RP.m_nProcessThreadID].m_matProj->Pop();
        return;
      }
		}

		FX_DrawPrimitive(eptTriangleStrip, nOffs + i * 4, 4);
	}

	EF_PopMatrix();
	m_RP.m_TI[m_RP.m_nProcessThreadID].m_matProj->Pop();
}

void CD3D9Renderer::RT_DrawStringW(IFFont_RenderProxy* pFont, float x, float y, float z, const wchar_t* pStr, const bool asciiMultiLine, const STextDrawContext& ctx) const
{
	SetProfileMarker("DRAWSTRINGW", CRenderer::ESPM_PUSH);

	if (GetS3DRend().IsStereoEnabled())
	{
		GetS3DRend().BeginRenderingTo(LEFT_EYE);
		pFont->RenderCallback(x, y, z, pStr, asciiMultiLine, ctx);
		GetS3DRend().EndRenderingTo(LEFT_EYE);

		GetS3DRend().BeginRenderingTo(RIGHT_EYE);
		pFont->RenderCallback(x, y, z, pStr, asciiMultiLine, ctx);
		GetS3DRend().EndRenderingTo(RIGHT_EYE);
	}
	else
	{
		pFont->RenderCallback(x, y, z, pStr, asciiMultiLine, ctx);
	}

	SetProfileMarker("DRAWSTRINGW", CRenderer::ESPM_POP);
}

void CD3D9Renderer::RT_DrawLines(Vec3 v[], int nump, ColorF& col, int flags, float fGround)
{
	if (m_bDeviceLost)
		return;

	int i;
	int st;
	HRESULT hr = S_OK;

	EF_SetColorOp(eCO_MODULATE, eCO_MODULATE, eCA_Texture | (eCA_Diffuse<<3), eCA_Texture | (eCA_Diffuse<<3));
	st = GS_NODEPTHTEST;
	if (flags & 1)
		st |= GS_BLSRC_SRCALPHA | GS_BLDST_ONEMINUSSRCALPHA;
	FX_SetState(st);
	CTexture::s_ptexWhite->Apply(0);

	DWORD c = D3DRGBA(col.r, col.g, col.b, col.a);
	uint32 nOffs;

	if (fGround >= 0)
	{
		SVF_P3F_C4B_T2F *vQuad = (SVF_P3F_C4B_T2F *)m_DynVB[POOL_P3F_COL4UB_TEX2F].LockVB(nump*2, nOffs);

		for (i=0; i<nump; i++)
		{
			vQuad[i*2+0].xyz.x = v[i][0]; vQuad[i*2+0].xyz.y = fGround; vQuad[i*2+0].xyz.z = 0;
			vQuad[i*2+0].color.dcolor = c;
			vQuad[i*2+0].st = Vec2(0.0f, 0.0f);
			vQuad[i*2+1].xyz = v[i];
			vQuad[i*2+1].color.dcolor = c;
			vQuad[i*2+1].st = Vec2(0.0f, 0.0f);
		}
		// We are finished with accessing the vertex buffer
		m_DynVB[POOL_P3F_COL4UB_TEX2F].UnlockVB();

		// Bind our vertex as the first data stream of our device
		m_DynVB[POOL_P3F_COL4UB_TEX2F].Bind();
		FX_SetFPMode();
		if (!FAILED(FX_SetVertexDeclaration(0, eVF_P3F_C4B_T2F)))
		{
			FX_DrawPrimitive(eptLineList, nOffs, nump * 2);
		}
	}
	else
	{
		SVF_P3F_C4B_T2F *vQuad = (SVF_P3F_C4B_T2F *)m_DynVB[POOL_P3F_COL4UB_TEX2F].LockVB(nump, nOffs);

		for (i=0; i<nump; i++)
		{
			vQuad[i].xyz = v[i];
			vQuad[i].color.dcolor = c;
			vQuad[i].st = Vec2(0, 0);
		}
		// We are finished with accessing the vertex buffer
		m_DynVB[POOL_P3F_COL4UB_TEX2F].UnlockVB();

		// Bind our vertex as the first data stream of our device
		m_DynVB[POOL_P3F_COL4UB_TEX2F].Bind();
		FX_SetFPMode();
		if (!FAILED(FX_SetVertexDeclaration(0, eVF_P3F_C4B_T2F)))
		{
			FX_DrawPrimitive(eptLineStrip, nOffs, nump);
		}
	}
}

void CD3D9Renderer::RT_Draw2dImage(float xpos,float ypos,float w,float h,CTexture *pTexture,float s0,float t0,float s1,float t1,float angle,DWORD col,float z)
{
	C2dImage img(xpos, ypos, w, h, pTexture, s0, t0, s1, t1, angle, col, z, 0);
	
	SetProfileMarker("DRAW2DIMAGE", CRenderer::ESPM_PUSH);

	if (GetS3DRend().IsStereoEnabled())
	{
		GetS3DRend().BeginRenderingTo(LEFT_EYE);
		RT_Draw2dImageInternal(&img, 1, true);
		GetS3DRend().EndRenderingTo(LEFT_EYE);

		GetS3DRend().BeginRenderingTo(RIGHT_EYE);
		RT_Draw2dImageInternal(&img, 1, false);
		GetS3DRend().EndRenderingTo(RIGHT_EYE);
	}
	else
	{
		RT_Draw2dImageInternal(&img, 1);
	}

	SetProfileMarker("DRAW2DIMAGE", CRenderer::ESPM_POP);
}

void CD3D9Renderer::RT_Push2dImage(float xpos,float ypos,float w,float h,CTexture *pTexture,float s0,float t0,float s1,float t1,float angle,DWORD col,float z,float stereoDepth)
{
	m_2dImages.Add(C2dImage(xpos, ypos, w, h, pTexture, s0, t0, s1, t1, angle, col, z, stereoDepth));
}

void CD3D9Renderer::RT_Draw2dImageList()
{
	if (m_2dImages.empty())
		return;
	
	SetProfileMarker("DRAW2DIMAGELIST", CRenderer::ESPM_PUSH);
	
	if (GetS3DRend().IsStereoEnabled())
	{
		GetS3DRend().BeginRenderingTo(LEFT_EYE);
		RT_Draw2dImageInternal(m_2dImages.Data(), m_2dImages.size(), true);
		GetS3DRend().EndRenderingTo(LEFT_EYE);

		GetS3DRend().BeginRenderingTo(RIGHT_EYE);
		RT_Draw2dImageInternal(m_2dImages.Data(), m_2dImages.size(), false);
		GetS3DRend().EndRenderingTo(RIGHT_EYE);
	}
	else
	{
		RT_Draw2dImageInternal(m_2dImages.Data(), m_2dImages.size());
	}

	SetProfileMarker("DRAW2DIMAGELIST", CRenderer::ESPM_POP);

	m_2dImages.resize(0);
}

void CD3D9Renderer::FlashRenderInternal(IFlashPlayer_RenderProxy* pPlayer, bool stereo, bool doRealRender)
{
	SetProfileMarker("FLASH_RENDERING", CRenderer::ESPM_PUSH);

	if (doRealRender)
	{
		if (GetS3DRend().IsStereoEnabled() && stereo)
		{
			GetS3DRend().BeginRenderingTo(LEFT_EYE);
			pPlayer->RenderCallback(IFlashPlayer_RenderProxy::EFT_StereoLeft, false);
			GetS3DRend().EndRenderingTo(LEFT_EYE);

			GetS3DRend().BeginRenderingTo(RIGHT_EYE);
			pPlayer->RenderCallback(IFlashPlayer_RenderProxy::EFT_StereoRight, true);
			GetS3DRend().EndRenderingTo(RIGHT_EYE);
		}
		else
		{
			pPlayer->RenderCallback(IFlashPlayer_RenderProxy::EFT_Mono);
		}
	}
	else
	{
		pPlayer->DummyRenderCallback(IFlashPlayer_RenderProxy::EFT_Mono, true);
	}

	SetProfileMarker("FLASH_RENDERING", CRenderer::ESPM_POP);
}

void CD3D9Renderer::FlashRenderPlaybackLocklessInternal(IFlashPlayer_RenderProxy* pPlayer, int cbIdx, bool stereo, bool finalPlayback, bool doRealRender)
{
	SetProfileMarker("FLASH_RENDERING", CRenderer::ESPM_PUSH);

	if (doRealRender)
	{
		if (GetS3DRend().IsStereoEnabled() && stereo)
		{
			GetS3DRend().BeginRenderingTo(LEFT_EYE);
			pPlayer->RenderPlaybackLocklessCallback(cbIdx, IFlashPlayer_RenderProxy::EFT_StereoLeft, false, false);
			GetS3DRend().EndRenderingTo(LEFT_EYE);

			GetS3DRend().BeginRenderingTo(RIGHT_EYE);
			pPlayer->RenderPlaybackLocklessCallback(cbIdx, IFlashPlayer_RenderProxy::EFT_StereoRight, finalPlayback, true);
			GetS3DRend().EndRenderingTo(RIGHT_EYE);
		}
		else
		{
			pPlayer->RenderPlaybackLocklessCallback(cbIdx, IFlashPlayer_RenderProxy::EFT_Mono, finalPlayback);
		}
	}
	else
	{
		pPlayer->DummyRenderCallback(IFlashPlayer_RenderProxy::EFT_Mono, true);
	}

	SetProfileMarker("FLASH_RENDERING", CRenderer::ESPM_POP);
}

void CD3D9Renderer::RT_PushRenderTarget(int nTarget, CTexture *pTex, SD3DSurface *pDepth, int nS)
{
  FX_PushRenderTarget(nTarget, pTex, pDepth, false, nS);
}

void CD3D9Renderer::RT_PopRenderTarget(int nTarget)
{
  FX_PopRenderTarget(nTarget);
}

void CD3D9Renderer::RT_Init()
{
  EF_Init();
}

void CD3D9Renderer::RT_CreateResource(SResourceAsync* pRes)
{
  if (pRes->eClassName == eRCN_Texture)
  {
    CTexture * pTex = NULL;

    if(pRes->nTexId)
    { // only create device texture
      pTex = CTexture::GetByID(pRes->nTexId);
      byte * arrData[6] = {pRes->pData,0,0,0,0,0};
      pTex->CreateDeviceTexture(arrData);
    }
    else
    { // create full texture
      char *pName = pRes->Name;
      char szName[128];
      if (!pName)
      {
        sprintf(szName, "$AutoDownloadAsync_%d", m_TexGenID++);
        pName = szName;
      }
      pTex = CTexture::Create2DTexture(pName, pRes->nWidth, pRes->nHeight, pRes->nMips, pRes->nTexFlags, pRes->pData, (ETEX_Format)pRes->nFormat, (ETEX_Format)pRes->nFormat);
    }

    SAFE_DELETE(pRes->pData);
    pRes->pResource = pTex;
    pRes->nReady = (CTexture::IsTextureExist(pTex));
  }
  else
  {
    assert(0);
  }

  delete pRes;
}
void CD3D9Renderer::RT_ReleaseResource(SResourceAsync* pRes)
{
  if (pRes->eClassName == eRCN_Texture)
  {
    CTexture *pTex = (CTexture *)pRes->pResource;
    pTex->Release();
  }
  else
  {
    assert(0);
  }

  delete pRes;
}

void CD3D9Renderer::RT_UnbindTMUs()
{
#if defined (DIRECT3D10)  
	ID3D11ShaderResourceView* pTex[16];
	for(uint32 i=0; i<16; ++i)
  {
		pTex[i] = (ID3D11ShaderResourceView*)NULL;
    CTexture::s_TexStages[i].m_Texture = NULL; 
  }
	m_pd3dDeviceContext->PSSetShaderResources(0, 16, pTex);
#endif 
}

void CD3D9Renderer::RT_UnbindResources()
{
#if defined (DIRECT3D10)  
    // Clear set Constant Buffers
    CHWShader_D3D::mfClearCB();

    ID3D11Buffer* pBuffers[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
    UINT StrideOffset[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
  
    m_pd3dDeviceContext->IASetIndexBuffer(NULL, DXGI_FORMAT_R16_UINT, 0);
    m_RP.m_pIndexStream = NULL;

    m_pd3dDeviceContext->IASetVertexBuffers( 0, 16, pBuffers, StrideOffset, StrideOffset);
    m_RP.m_VertexStreams[0].pStream = NULL;

    m_pd3dDeviceContext->IASetInputLayout(NULL); 
    m_pLastVDeclaration=NULL; 
#endif 
}

void CD3D9Renderer::RT_ReleaseRenderResources()
{
	m_cEF.mfReleasePreactivatedShaderData();
	m_cEF.m_Bin.InvalidateCache();
	m_cEF.m_Bin.m_BinPaths.clear();
  if (!m_DevBufMan.Cleanup()) 
    CryLogAlways("could not free all buffers from CDevBufferMan!"); 
  ForceFlushRTCommands();

	for (uint i=0; i<CLightStyle::m_LStyles.Num(); i++)
	{
		delete CLightStyle::m_LStyles[i];
	}
	CLightStyle::m_LStyles.Free();

#ifndef _RELEASE
	m_cEF.mfFlushFullPLCombinations();
#endif

  int i;
  FX_PipelineShutdown();
#if defined (DIRECT3D10)
	ID3D11RenderTargetView *pRTV[RT_STACK_WIDTH] = { NULL }; 
	m_pd3dDeviceContext->OMSetRenderTargets(RT_STACK_WIDTH, pRTV, NULL);
#endif
  m_nMaxRT2Commit = -1;
  for (i=0; i<4; i++)
  {
    //m_pNewTarget[i] = NULL;
    //m_pCurTarget[i] = NULL;
  }















}
void CD3D9Renderer::RT_CreateRenderResources()
{
  EF_Init();

	if (m_pPostProcessMgr)
	{
		m_pPostProcessMgr->CreateResources();
	}
}

void CD3D9Renderer::RT_PrecacheDefaultShaders()
{
	SShaderCombination cmb;
	m_cEF.m_ShaderStereo->mfPrecache(cmb, true, true, NULL);

#ifndef EXCLUDE_SCALEFORM_SDK
	SF_PrecacheShaders();
#endif
}

//////////////////////////////////////////////////////////////////////////

void CD3D9Renderer::StartLoadtimeFlashPlayback(ILoadtimeCallback* pCallback)
{
	// make sure we can't access loading mode twice!
	assert(!m_pRT->m_pLoadtimeCallback);
	if (m_pRT->m_pLoadtimeCallback)
	{
		return;
	}

	// TODO: check for r_shadersnocompile to prevent issue with device access from render load thread
	if (pCallback)
	{
		FlushRTCommands(true, true, true);

		m_pRT->m_pLoadtimeCallback = pCallback;
		SetViewport(0, 0, GetWidth(), GetHeight());
		m_pRT->RC_StartVideoThread();

		// wait until render thread has fully processed the start of the video
		// to reduce the congestion on the IO reading (make sure nothing else
		// beats the video to actually start reading something from the DVD)
		while (m_pRT->m_eVideoThreadMode != SRenderThread::eVTM_Active)
		{
			m_pRT->FlushAndWait();
			Sleep(0);
		}
	}
}

void CD3D9Renderer::StopLoadtimeFlashPlayback()
{
	if (m_pRT->m_pLoadtimeCallback)
	{
		FlushRTCommands(true, true, true);

		m_pRT->RC_StopVideoThread();

		// wait until render thread has fully processed the shutdown of the loading thread
		while (m_pRT->m_eVideoThreadMode != SRenderThread::eVTM_Disabled)
		{
			m_pRT->FlushAndWait();
			Sleep(0);
		}	

		m_pRT->m_pLoadtimeCallback = 0;

		m_pRT->RC_BeginFrame();
		SetState(GS_BLSRC_SRCALPHA|GS_BLDST_ONEMINUSSRCALPHA|GS_NODEPTHTEST);
		Draw2dImage(0, 0, 800.f, 600.f, -1,
			0.0f,0.0f,1.0f,1.0f, 0.f, 0.f,0.f,0.f,1.f,0.f);

#if !defined(XENON) && !defined(PS3) && !defined(CAFE)
		if (CRenderer::CV_r_textureswarmup)
		{
			iLog->Log("--- Warming-up textures...");
			iLog->UpdateLoadingScreen(0);
			m_pRT->RC_WarmupTextures();
		}
#endif

		// Blit the accumulated commands from the renderloading thread into the current fill command queue
		// : Currently hacked into the RC_UpdateMaterialConstants command, but will be generalized soon
		void* buf = m_pRT->m_Commands[m_pRT->m_nCurThreadFill].Grow(m_pRT->m_CommandsLoading.size());
		memcpy(buf, m_pRT->m_CommandsLoading.begin(), m_pRT->m_CommandsLoading.size());
		m_pRT->m_CommandsLoading.resize(0);
	}
}
